﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Xml;

namespace BinocularVision
{
    public class WebCam 
    {
        #region Fields
        private int webCamDeviceNr;
        private int imageWidth;
        private int imageHeight;
        private int frameRate;

        private Bitmap image;
        private CaptureDevice capDevice;

        private static Mutex imageMut = new Mutex(); // Mutex used to make sure only one thread accesses the image object at any given time
        #endregion  

        #region Internal methods
        internal void UpdateReading()
        {
            IntPtr ip = IntPtr.Zero;
            ip = capDevice.GetBitMap();
            imageMut.WaitOne();
            if (image != null)
            {
                image.Dispose();
            }
            image = null;
            image = new Bitmap(capDevice.Width, capDevice.Height, capDevice.Stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, ip);
            image.RotateFlip(RotateFlipType.RotateNoneFlipY);
            imageMut.ReleaseMutex();
            if (ip != IntPtr.Zero)
            {
                Marshal.FreeCoTaskMem(ip);
                ip = IntPtr.Zero;
            }
        }

        internal void Disconnect()
        {
            capDevice.Dispose();
        }
        #endregion

        #region Public methods

        public void Initialize()
        {
            capDevice = new CaptureDevice(webCamDeviceNr, frameRate, imageWidth, imageHeight);
        }

        public void Start()
        {
            capDevice.Start();
        }
        #endregion

        #region Properties
        public Bitmap ReadingAsBitmap
        {
            get 
            {
                if (image != null)
                {
                    imageMut.WaitOne();
                    Bitmap tmpBitmap = new Bitmap(image);
                    imageMut.ReleaseMutex();
                    return tmpBitmap;
                }
                else
                {
                    return null;
                }
            }
        }

        public int WebCamDeviceNr
        {
            get { return webCamDeviceNr; }
            set { webCamDeviceNr = value; }
        }

        public int ImageWidth
        {
            get { return imageWidth; }
            set { imageWidth = value; }
        }

        public int ImageHeight
        {
            get { return imageHeight; }
            set { imageHeight = value; }
        }

        public int FrameRate
        {
            get { return frameRate; }
            set { frameRate = value; }
        }
        #endregion

    }
}
